﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Input;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

using ProtoImaginer.ProtoControl;
using ProtoImaginer.Models;

namespace ProtoImaginer.ProtoPage
{
    public partial class PageView : PhoneApplicationPage
    {
        //for SEMIFINAL demo only
        public static BitmapImage tempImg;

        //end for SEMIFINAL demo only
        //pinch related global variable
        private double initialScale;

        private ApplicationBarIconButton addControlButton;
        private ApplicationBarIconButton presentButton;
        private ApplicationBarIconButton delControlButton;
        private ApplicationBarIconButton linkPageButton;

        private ControlAtom highlighted;
        private Models.Page page;
        public Models.Image image;

        public PageView()
        {
            //this should deply all the background UI.
            InitializeComponent();

            addControlButton = (ApplicationBarIconButton)ApplicationBar.Buttons[0];
            presentButton = (ApplicationBarIconButton)ApplicationBar.Buttons[1];
            delControlButton = (ApplicationBarIconButton)ApplicationBar.Buttons[2];
            linkPageButton = (ApplicationBarIconButton)ApplicationBar.Buttons[3];
        }
        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            page = Models.ProtoDataContext.LoadPageByPK(NavigationContext.QueryString["pageId"]);
            image = Models.ProtoDataContext.LoadImagesByPageId(page.PageId);
            initialScale = 1;
            Scale = 1;

            UpdatePage();
        }

        #region UI handler
        /*=====================================================================
         * Application bar
         *===================================================================*/

        private void AddControlButtonClick(object sender, EventArgs e)
        {
            AddControl();
        }
        private void PresentButtonClick(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/ProtoDemo/ProjectDemo.xaml?pageId=" + page.PageId, UriKind.Relative));
        }
        private void DelControlButtonClick(object sender, EventArgs e)
        {
            DelControl();
        }
        private void LinkPageButtonClick(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/ProtoPage/SelectPage.xaml?controlId=" + highlighted.GetControl().ControlId, UriKind.Relative));
        }
        /*=====================================================================
         * Gestures on Canvas, pinch session.
         *===================================================================*/

        private void CanvasPinchStarted(object sender, PinchStartedGestureEventArgs e)
        {
            initialScale = ((CompositeTransform)Canvas.RenderTransform).ScaleX;
        }

        private void CanvasPinchDelta(object sender, PinchGestureEventArgs e)
        {
            var finger1 = e.GetPosition(Canvas, 0);
            var finger2 = e.GetPosition(Canvas, 1);

            Canvas.RenderTransformOrigin = new Point(
                (finger2.X + finger1.X) / 2 / Canvas.ActualWidth,
                (finger2.Y + finger1.Y) / 2 / Canvas.ActualHeight);

            var transform = (CompositeTransform)Canvas.RenderTransform;
            transform.ScaleX = initialScale * e.DistanceRatio;
            transform.ScaleY = transform.ScaleX;
        }

        private void CanvasPinchCompleted(object sender, PinchGestureEventArgs e)
        {
            Scale = CanvasTransformation.ScaleX;
        }


        /*=====================================================================
         * Gestures on Canvas, drag session.
         *===================================================================*/

        //disable pivot's drag event.
        private void CanvasDragStarted(object sender, DragStartedGestureEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;
            }
        }

        //drag canvas around.
        private void CanvasDragDelta(object sender, DragDeltaGestureEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;

                Canvas.Margin = new Thickness(
                        Canvas.Margin.Left + e.HorizontalChange,
                        Canvas.Margin.Top + e.VerticalChange,
                        Canvas.Margin.Right - e.HorizontalChange,
                        Canvas.Margin.Bottom - e.VerticalChange);
            }
        }

        //enable pivot's drag event.
        private void CanvasDragCompleted(object sender, DragCompletedGestureEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;
            }
        }

        /*=====================================================================
         * Gestures on Canvas, tap session.
         *===================================================================*/

        //di-highlight current control item, if applicable
        private void CanvasTap(object sender, Microsoft.Phone.Controls.GestureEventArgs e)
        {
            Updatehighlighted(null);
        }
        //reset canvas scale and position.
        private void GraphicViewDoubleTap(object sender, Microsoft.Phone.Controls.GestureEventArgs e)
        {
            CanvasTransformation.ScaleX = 1;
            CanvasTransformation.ScaleY = 1;

            Canvas.Margin = new Thickness(0, 0, 0, 0);
        }

        /*=====================================================================
         * Gestures on Control items, tap session.
         *===================================================================*/

        //show outline and four active dot.
        private void ControlAtomTap(object sender, Microsoft.Phone.Controls.GestureEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;

                //show outline of active control item.
                ((ControlAtom)sender).Outline(true);

                //enable delete and linkTo button when control item highlighted
                Updatehighlighted((ControlAtom)sender);
            }
        }
        /*=====================================================================
         * Gestures on Control items, drag session.
         *===================================================================*/

        //disable parents' drag gestures
        private void ControlDragStarted(object sender, DragStartedGestureEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;

                //de-highlight other control items.
                if(highlighted != sender)
                    Updatehighlighted(null);
            }
        }

        //drag control item around.
        private void ControlDragDelta(object sender, DragDeltaGestureEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;

                Canvas.SetLeft((UIElement)sender, Canvas.GetLeft((UIElement)sender) + e.HorizontalChange / Scale);
                Canvas.SetTop((UIElement)sender, Canvas.GetTop((UIElement)sender) + e.VerticalChange / Scale);
            }
        }

        //enable pivot's drag event & make sure control item is within image.
        private void ControlDragCompleted(object sender, DragCompletedGestureEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;

                CheckRangeWithinCanvas((UIElement)sender);
                ((ControlAtom)sender).SetPosition(
                    Canvas.GetLeft((ControlAtom)sender) * 4/3, 
                    Canvas.GetTop((ControlAtom)sender) * 4/3);
            }
        }
        #endregion

        #region UI control
        /*=====================================================================
         * UI misc.
         *===================================================================*/
        public void UpdatePage() {
            PageTitle.Text = page.PageTitle;

            GraphicViewDoubleTap(null, null);

            //load image
            BitmapImage img = new BitmapImage();
            if (image.ImageId != MainPage.tempImg.ImageId || PageView.tempImg == null)
                img.SetSource(Application.GetResourceStream(new Uri(@image.ImageSource, UriKind.Relative)).Stream);
            else
                img = PageView.tempImg;

            Image.Source = img;
            ControlContainer.Children.Clear();
            //load conrols
            var controlData = Models.ProtoDataContext.LoadControlsByImageId(image.ImageId);
            foreach (Models.Control control in controlData)
                AddControl(control);
        }
        public void CheckRangeWithinCanvas(UIElement controlItem)
        {
            if (Canvas.GetLeft(controlItem) < 0)
                Canvas.SetLeft(controlItem, 0);
            else if (Canvas.GetLeft(controlItem) + ((ControlAtom)controlItem).Width > ControlContainer.Width)
                Canvas.SetLeft(controlItem, ControlContainer.Width - ((ControlAtom)controlItem).Width);

            if (Canvas.GetTop(controlItem) < 0)
                Canvas.SetTop(controlItem, 0);
            else if (Canvas.GetTop(controlItem) + ((ControlAtom)controlItem).Height > ControlContainer.Height)
                Canvas.SetTop(controlItem, ControlContainer.Height - ((ControlAtom)controlItem).Height);
        }
        public void ButtonTrigger()
        {
            if (highlighted == null)
            {
                delControlButton.IsEnabled = false;
                linkPageButton.IsEnabled = false;
            }
            else
            {
                delControlButton.IsEnabled = true;
                linkPageButton.IsEnabled = true;
            }
        }
        /*=====================================================================
         * Edit Control.
         *===================================================================*/

        //create new control
        private void AddControl()
        {
            //initialize new control item.
            ControlAtom newItem = new ControlAtom(this);
            //UI layer stuff
            try
            {
                ControlContainer.Children.Add(newItem);
                //bind listeners
                BindControlItemListener(newItem);

                Canvas.SetLeft(newItem, 100);
                Canvas.SetTop(newItem, 200);
            }
            catch (Exception e) {
                MessageBox.Show(e.ToString());
            }

        }

        //load control from db
        private void AddControl(Models.Control control) {
            ControlAtom newItem = new ControlAtom(this, control);

            try
            {
                ControlContainer.Children.Add(newItem);

                //bind listeners
                BindControlItemListener(newItem);
                newItem.Width *= initialScale * 3 / 4;
                newItem.Height *= initialScale * 3 / 4;

                Canvas.SetLeft(newItem, control.Control_Top_Left_Point_X_Coordinate * Scale * 3 / 4);
                Canvas.SetTop(newItem, control.Control_Top_Left_Point_Y_Coordinate * Scale * 3 / 4);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }
        private void DelControl()
        {
            if (highlighted != null)
            {
                //ui layer
                ControlContainer.Children.Remove(highlighted);

                //db layer
                highlighted.RemoveControl();

                //misc
                Updatehighlighted(null);
                ButtonTrigger();
            }
        }
        private void Updatehighlighted(ControlAtom newhighlighted)
        {
            highlighted = newhighlighted;

            foreach (ControlAtom control in ControlContainer.Children)
                control.Outline(false);

            if (highlighted != null)
                highlighted.Outline(true);

            ButtonTrigger();
        }
        private void BindControlItemListener(ControlAtom newItem)
        {
            GestureListener listener = GestureService.GetGestureListener(newItem);
            listener.Tap += ControlAtomTap;
            listener.DragStarted += ControlDragStarted;
            listener.DragDelta += ControlDragDelta;
            listener.DragCompleted += ControlDragCompleted;
        }
        public double Scale
        {
            set;
            get;
        }
        #endregion

        public String GetImageId() {
            return image.ImageId;
        }
    }
}